package com.ev.apis.controller.custom;

import com.ev.apis.model.DsResultResponse;
import com.ev.custom.service.*;
import com.ev.framework.annotation.EvApi;
import com.ev.framework.annotation.EvApiByToken;
import com.ev.apis.model.UserResponse;
import com.ev.framework.annotation.Log;
import com.ev.framework.config.Constant;
import com.ev.framework.config.ConstantForDevice;
import com.ev.framework.utils.*;
import com.ev.system.domain.DeptDO;
import com.ev.system.domain.OpLogDO;
import com.ev.system.domain.UserDO;
import com.ev.framework.il8n.MessageSourceHandler;
import com.ev.system.service.DeptService;
import com.ev.system.service.MenuService;
import com.ev.system.service.OpLogService;
import com.ev.system.service.UserService;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author yunian
 * @date 2018/6/17
 */
@Api(value = "/",tags = "App登录API")
@RestController
public class AppLoginController {
    @Value("${server.port}")
    private String port;
    @Value("${mqttUrl}")
    private String mqttUrl;
    @Autowired
    private UserService userService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private OpLogService opLogService;
    @Autowired
    private TaskMainService taskMainService;
    @Autowired
    private PatrolRecordService patrolRecordService;
    @Autowired
    private RepairEventService repairEventService;
    @Autowired
    private UpkeepRecordService upkeepRecordService;
    @Autowired
    private DailyReportService dailyReportService;
    @Autowired
    private WeekReportService weekReportService;
    @Autowired
    private ReimApplyService reimApplyService;
    @Autowired
    private OverTimeApplyService overTimeApplyService;
    @Autowired
    private LeaveApplyService leaveApplyService;
    @Autowired
    private PayApplyService payApplyService;
    @Autowired
    private NewsService newsService;
    @Autowired
    private NoticeService noticeService;


    @Autowired
    private MessageSourceHandler messageSourceHandler;

    @Autowired
    private MenuService menuService;

    @Autowired
    private DeptService deptService;


    @EvApi(value = "/apis/user/checkToken", method = RequestMethod.POST, apiTitle = "Token校验")
    public R checkOfToken(@ApiParam(value = "userToken", required = true) @RequestParam(value = "token", required = true) String token,
                          @ApiParam(value = "用户名", required = true) @RequestParam(value = "username", required = true) String username,
                          @ApiParam(value = "密码", required = true) @RequestParam(value = "password", required = true) String password) {

        if (StringUtils.isNotEmpty(token)) {
            //校验令牌是否有效
            Object obj = redisTemplate.opsForValue().get(Constant.REDIS_USER_TOKEN_PREFIX + token);

            Map<String,Object> results = Maps.newHashMap();
            if (obj == null) {
                //令牌过期重新生成返回
                password = MD5Utils.encrypt(username, password);
                UsernamePasswordToken tokens = new UsernamePasswordToken(username, password);
                Subject subject = SecurityUtils.getSubject();
                try{
                    subject.login(tokens);
                    String userToken = ShiroUtils.getSubjct().getSession().getId().toString();
                    UserResponse userResponse = new UserResponse();
                    UserDO userDO = userService.findByUsername(username);
                    BeanUtils.copyProperties(userDO,userResponse);
                    userResponse.setToken(userToken);

                    results.put("userInfo",userResponse);
                    results.put("msg",messageSourceHandler.getMessage("login.token.isExpired",null));
                    results.put("isLate","true");
                    return R.ok(results);
                }catch(AuthenticationException e){
                    return R.error(messageSourceHandler.getMessage("login.userOrPassword.inCorrect",null));
                }
            }else{
                //令牌有效，返回验证信息
                results.put("isLate","false");
                return R.ok(results);
            }
        } else {
            //令牌为空！
            return R.error(messageSourceHandler.getMessage("login.token.isEmpty",null));
        }
    }

    @Log(operModule = "登录管理",operType = "登录",operDesc = "登录系统")
    @EvApi(value = "/apis/user/login",method = RequestMethod.POST,apiTitle = "登录")
    public R login(@ApiParam(value = "用户名",required = true)@RequestParam(value = "username",required = true)String username,
                   @ApiParam(value = "密码",required = true)@RequestParam(value = "password",required = true)String password){
        password = MD5Utils.encrypt(username, password);
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            String userToken = ShiroUtils.getSubjct().getSession().getId().toString();
            //session缓存一个月。
            //redisTemplate.opsForValue().set(Constant.REDIS_USER_TOKEN_PREFIX+userToken,username,3600*24*30, TimeUnit.SECONDS);
            UserResponse userResponse = new UserResponse();
            UserDO userDO = userService.findByUsername(username);
            BeanUtils.copyProperties(userDO,userResponse);
            userResponse.setToken(userToken);
            DeptDO dept = deptService.get(userDO.getDeptId());
            userResponse.setDeptName(dept == null?null:dept.getName());
            userResponse.setPort(port);
            userResponse.setMqttUrl(mqttUrl);
            //获取权限列表
            Set<String> permSet = menuService.listPerms(userDO.getUserId());
            Map<String,Object> results = Maps.newHashMap();
            results.put("userInfo",userResponse);
            results.put("permSet",permSet);
            return R.ok(results);
        } catch (AuthenticationException e) {
            return R.error(e.getMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @EvApiByToken(value = "/apis/user/logout",method = RequestMethod.POST,apiTitle = "注销")
    public R logout(HttpServletRequest request){
        OpLogDO operlog = new OpLogDO();
        operlog.setOpModule("登陆管理"); // 操作模块
        operlog.setOpType("登出"); // 操作类型
        operlog.setOpDesc("登出系统"); // 操作描述
        operlog.setOpMethod("com.ev.apis.controller.custom.AppLoginController.logout");
        operlog.setOpRequParam(request.toString()); // 请求参数
        operlog.setOpRespParam("login.success"); // 返回结果
        operlog.setOpUserId(ShiroUtils.getUserId()); // 请求用户ID
        operlog.setOpUserName(ShiroUtils.getUser()==null?null:ShiroUtils.getUser().getUsername()); // 请求用户名称
        operlog.setOpIp(IPUtils.getIpAddr(request)); // 请求IP
        operlog.setOpUri(request.getRequestURI()); // 请求URI
        operlog.setCreateTime(new Date()); // 创建时间
        opLogService.save(operlog);

        String userToken = request.getHeader("Authorization");
        //redisTemplate.delete(Constant.REDIS_USER_TOKEN_PREFIX+userToken);
        ShiroUtils.logout();
        return R.ok(messageSourceHandler.getMessage("login.success",null));
    }

    @Transactional(rollbackFor = Exception.class)
    @EvApiByToken(value = "/apis/user/appResetPasswd",method = RequestMethod.POST,apiTitle = "修改个人密码")
    public R appResetPasswd(HttpServletRequest request,
                          @ApiParam(value = "旧密码",required = true)@RequestParam(value = "oldpasswd")String oldpasswd,
                          @ApiParam(value = "新密码",required = true)@RequestParam(value = "newpasswd")String newpasswd,
                          @ApiParam(value = "新密码确认",required = true)@RequestParam(value = "newpasswd")String newpasswordConfirm){
        String userToken = request.getHeader("Authorization");
        ///根据key获取缓存中的用户名
        //String username = redisTemplate.opsForValue().get(Constant.REDIS_USER_TOKEN_PREFIX+userToken);
        UserDO userDO = ShiroUtils.getUser();
        try {
            int code = userService.appResetPasswd(userDO,oldpasswd,newpasswd);
            if(code == 500){
                return R.error(messageSourceHandler.getMessage("login.oldPassword.error",null));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.ok(messageSourceHandler.getMessage("login.update.success",null));
    }

    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
        List<String> excludes = new ArrayList<>();

        if (excludes == null || excludes.isEmpty()) {
            return false;
        }

        String url = request.getServletPath();
        for (String pattern : excludes) {
            Pattern p = Pattern.compile("^" + pattern);
            Matcher m = p.matcher(url);
            if (m.find()) {
                return true;
            }
        }

        return false;
    }

    @EvApiByToken(value = "/apis/index/getInfo", method = RequestMethod.POST, apiTitle = "查询主页数据")
    @ApiOperation("查询主页数据")
    public R getInfo(@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
                     @ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize) {
        UserDO userDO = ShiroUtils.getUser();
        Long userId = userDO.getUserId();
        Long deptId = userDO.getDeptId();
        Map<String,Object> result = Maps.newHashMap();
        // 任务获取待办事项数量
        Map<String,Object> taskMain = Maps.newHashMap();
        taskMainService.getUserWaitingCount(userId, ConstantForDevice.WAITING_CHECK, null, taskMain);
        taskMainService.getUserWaitingCount(userId, ConstantForDevice.WAITING_DEAL, null, taskMain);
        result.put("taskMain",taskMain);
        // 巡检获取待处理数量
        Map<String, Object> patrolRecord = this.patrolRecordService.getBacklog(userId, null);
        result.put("patrolRecord",patrolRecord);

        // 维修待处理数量
        Map<String, Object> repairEvent = repairEventService.getCountBacklog(userId, deptId);
        result.put("repairEvent",repairEvent);

        // 保养
        Map<String,Object> query = Maps.newHashMap();
        query.put("engineerId", userId);
        query.put("result", ConstantForDevice.WAITING_DEAL);//工单状态{56待处理，57待验收，58已验收}
        int upkeepRecord = upkeepRecordService.countOfWaitingDo(query);
        result.put("upkeepRecord",upkeepRecord);

        // 日报发给我的数量
        query.clear();
        query.put("beSentPeopleId",userId);
        int dailyReport = dailyReportService.countOfQuantyForward(query);
        result.put("dailyReport",dailyReport);

        // 周报发给我的数量
        int weekReport = weekReportService.countOfQuantyForward(query);
        result.put("weekReport",weekReport);

        // 报销
        query.clear();
        query.put("assignId", userId);
        query.put("statusOfCount", ConstantForDevice.APPLY_APPROVING);
        Map<String, Object> reimApply = this.reimApplyService.countForMap(query);
        result.put("reimApply", Integer.parseInt(reimApply.get("counts").toString()));

       // 加班
        Map<String, Object> overTimeApply = this.overTimeApplyService.countForMap(query);
        result.put("overTimeApply", Integer.parseInt(overTimeApply.get("counts").toString()));

        // 请假
        Map<String, Object> leaveApply = leaveApplyService.countForMap(query);
        result.put("leaveApply", Integer.parseInt(leaveApply.get("counts").toString()));

        // 付款
        Map<String, Object> payApply = this.payApplyService.countForMap(query);
        result.put("payApply", Integer.parseInt(payApply.get("counts").toString()));

        // 新闻公告
        query.clear();
        query.put("offset", (pageno - 1) * pagesize);
        query.put("limit", pagesize);
        List<Map<String, Object>> data = this.newsService.listForMap(query);
        int total = this.newsService.countForMap(query);
        if (data.size() > 0) {
            DsResultResponse dsRet = new DsResultResponse();
            dsRet.setDatas(data);
            dsRet.setPageno(pageno);
            dsRet.setPagesize(pagesize);
            dsRet.setTotalRows(total);
            dsRet.setTotalPages((int) (total + pagesize - 1) / pagesize);
            result.put("news", dsRet);
        }

        // 未读消息
        query.clear();
        query.put("signStatus", "0");
        query.put("toUserId", userId);
        int count = noticeService.countForMap(query);
        Map<String, Object> results = Maps.newHashMap();
        result.put("notReadCount",count);

        return R.ok(result);

    }

}
